<?php

namespace App\Console\Commands;

use App\Libraries\Taobao;
use App\Models\Items;
use App\Models\ItemsCate;
use Illuminate\Console\Command;
use GuzzleHttp\Client;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Redis;

class VeTbkApiCrawlerGoods extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'vegoods:crawler';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'crawler tb goods data';

    private $crawlerMaxPageCount = 20;//每个分类最多采集2000个数据够了
    private $crawlerPageCounter = 1;//采集分页计数器 到20 停止
    private $concurrency    = 6;  // 同时并发抓取
    private $tobe_crawler_cate_goods = null;//要采集的分类

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $client = new Client();
        $this->tobe_crawler_cate_goods = ItemsCate::where("parent_id",">",0)->get()->toArray();

        if (!Str::startsWith(env('APP_URL'), 'huiyouduoapp.com'))
        {
            //非生成环境 采集部分数据作为测试即可
            $this->crawlerMaxPageCount = 3;
            $this->tobe_crawler_cate_goods = ItemsCate::where("parent_id",">",0)->orderBy(\DB::raw('RAND()'))->take(5)->get()->toArray();
        }

        if(!empty($this->tobe_crawler_cate_goods))
        {
            foreach ($this->tobe_crawler_cate_goods as $k=>$v)
            {
                $requests = function ($total) use ($client,$v) {
                    for ($i=1;$i<=$this->crawlerMaxPageCount;$i++)
                    {
                        $uri = sprintf(config('vetbk.super_search_goods_by_cate_name_api_url'),$v['title'],$i);
                        yield function () use ($client,$uri) {
                            return $client->getAsync($uri);
                        };
                    }
                };
                $pool = new Pool($client,$requests($this->crawlerMaxPageCount),[
                    'concurrency' => $this->concurrency,
                    'fulfilled'   => function ($response, $index) use ($v) {

                        $res = json_decode($response->getBody(),true);
                        //获取到数据
                        $page_goods_data = $res['result_list'] ?? [];

                        if(!empty($page_goods_data)) $this->dataClean($page_goods_data,$v);

                        $this->info("excute success");

                       // $this->info("请求第 $index 个请求，用户 ");

                        //$this->countedAndCheckEnded();
                    },
                    'rejected' => function ($reason, $index){
                        $this->error("rejected" );
                        $this->error("rejected reason: " . $reason );
                    },
                ]);
                // 开始发送请求
                $promise = $pool->promise();
                $promise->wait();
            }
        }
    }

    /**
     * @desc 根据优惠券正则提取优惠券金额
     * @param string $coupon_info
     */
    private function getCouponPrice($coupon_info = "")
    {
        $preg = '/.*?减(\d+)元/';
        preg_match_all($preg,$coupon_info,$match);
        return $match[1][0] ?? 0;
    }

    /**
     * @desc 采集的数据清洗 去重，入库
     */
    public function dataClean($ori_data = [],$ori_cate_data = [])
    {
        if(empty($ori_data) || empty($ori_cate_data)) return false;

        foreach ($ori_data as $k=>$v)
        {
            //检测是否已经采集过当前商品 采集过跳过,没采集过 入库 并加入到采集过的id集合中
            if(Redis::sismember(env('ITEMS_CRAWLERED_COLLECTIONS_REDIS_KEY'),$v['num_iid'])) continue;
            else
            {
                //没有采集过 入redis集合
                Redis::sadd(env('ITEMS_CRAWLERED_COLLECTIONS_REDIS_KEY'),$v['num_iid']);
                //新增字段
                $insert_data = $v;
                $insert_data['cid'] = $ori_cate_data['id'];
                $insert_data['cate_leaf_id'] = $ori_cate_data['parent_id'];
                $insert_data['coupon_price'] = $this->getCouponPrice($v['coupon_info']);
                $insert_data['coupon_after_price'] = max(0,$v['zk_final_price'] - $insert_data['coupon_price']);
                $insert_data['small_images'] = empty($v['small_images']) ? "" : json_encode($v['small_images']);
                $insert_data['shop_dsr'] = sprintf("%.1f", $v['shop_dsr'] / 10000);
                $insert_data['detail_images'] = Taobao::getGoodsDetail($v['num_iid']);
                $insert_data['short_title'] = is_array($v['short_title']) ? ($v['short_title'][0] ?? "") : $v['short_title'];
                Items::create($insert_data);
            }
        }
        usleep(5000);
    }
}
